/**
 * 高亮管理器
 * 负责在编辑器中显示差异高亮
 */

class HighlightManager {
    /**
     * 构造函数
     * @param {HTMLTextAreaElement} editor - 文本编辑器元素
     * @param {HTMLDivElement} overlay - 高亮覆盖层元素
     * @param {HTMLDivElement} lineNumbers - 行号显示元素
     */
    constructor(editor, overlay, lineNumbers) {
        this.editor = editor;
        this.overlay = overlay;
        this.lineNumbers = lineNumbers;
        this.diffs = [];
        
        // 绑定滚动同步
        this.setupScrollSync();
        
        // 绑定内容变化事件以更新行号
        const updateLineNumbersHandler = () => {
            this.updateLineNumbers();
        };
        
        this.editor.addEventListener('input', updateLineNumbersHandler);
        this.editor.addEventListener('paste', updateLineNumbersHandler);
        
        // 初始化行号
        this.updateLineNumbers();
    }
    
    /**
     * 设置滚动同步
     */
    setupScrollSync() {
        let isScrolling = false;
        
        const syncScroll = () => {
            if (!isScrolling) {
                isScrolling = true;
                this.overlay.scrollTop = this.editor.scrollTop;
                this.overlay.scrollLeft = this.editor.scrollLeft;
                this.lineNumbers.scrollTop = this.editor.scrollTop;
                setTimeout(() => isScrolling = false, 10);
            }
        };
        
        this.editor.addEventListener('scroll', syncScroll);
    }
    
    /**
     * 更新行号显示
     */
    updateLineNumbers() {
        const lineCount = this.editor.value.split('\n').length || 1;
        let lineNumbersHTML = '';
        
        for (let i = 1; i <= lineCount; i++) {
            lineNumbersHTML += `<div class="line-number">${i}</div>`;
        }
        
        this.lineNumbers.innerHTML = lineNumbersHTML;
    }
    
    /**
     * 更新差异高亮
     * @param {Array} diffs - 差异数组
     * @param {number} editorNum - 编辑器编号（1或2）
     */
    updateHighlights(diffs, editorNum) {
        this.diffs = diffs;
        this.renderHighlights(editorNum);
        this.updateLineNumbers();
    }
    
    /**
     * 清除高亮
     */
    clearHighlights() {
        this.diffs = [];
        this.overlay.innerHTML = '';
        this.updateLineNumbers();
    }
    
    /**
     * 渲染高亮
     * @param {number} editorNum - 编辑器编号（1或2）
     */
    renderHighlights(editorNum) {
        // 获取编辑器内容行
        const lines = this.editor.value.split('\n');
        
        // 创建高亮内容
        const highlightContent = this.createHighlightContent(lines, editorNum);
        
        // 更新覆盖层
        this.overlay.innerHTML = highlightContent;
        
        // 调试：确认高亮内容已应用
        console.log('Highlight content for editor ' + editorNum + ':', highlightContent);
        
        // 检查是否有高亮内容
        if (highlightContent.includes('diff-')) {
            console.log('Highlight classes found in editor ' + editorNum);
        } else {
            console.log('No highlight classes found in editor ' + editorNum);
        }
    }
    
    /**
     * 创建高亮内容
     * @param {Array} lines - 行数组
     * @param {number} editorNum - 编辑器编号
     * @returns {string} 高亮HTML内容
     */
    createHighlightContent(lines, editorNum) {
        // 简化策略：直接遍历每一行，检查是否匹配任何差异
        // 这样确保所有行都被渲染，不会出现"滚动到才显示"的问题
        
        let content = '';
        const matchedDiffs = new Set(); // 记录已匹配的差异，避免重复匹配
        
        for (let i = 0; i < lines.length; i++) {
            const line = lines[i];
            let lineClass = '';
            
            // 检查这一行是否匹配任何差异
            for (const diff of this.diffs) {
                // 如果这个差异已经被匹配过，跳过
                if (matchedDiffs.has(diff)) {
                    continue;
                }
                
                // 根据差异类型和编辑器编号判断是否应该在这个编辑器中显示
                const shouldShow = (diff.type === 'added' && editorNum === 2) ||
                                  (diff.type === 'removed' && editorNum === 1) ||
                                  (diff.type === 'modified');
                
                if (!shouldShow) {
                    continue;
                }
                
                // 检查这一行是否匹配这个差异
                if (this.doesLineMatchDiff(line, diff, editorNum)) {
                    // 确定高亮类型
                    if (diff.type === 'added') {
                        lineClass = 'diff-added';
                    } else if (diff.type === 'removed') {
                        lineClass = 'diff-removed';
                    } else if (diff.type === 'modified') {
                        lineClass = 'diff-modified';
                    }
                    
                    // 标记这个差异已被匹配
                    matchedDiffs.add(diff);
                    
                    // 找到匹配后立即停止，一行只匹配一个差异
                    break;
                }
            }
            
            // 创建行元素
            if (lineClass) {
                // 根据类名设置内联样式
                let inlineStyle = '';
                switch (lineClass) {
                    case 'diff-added':
                        inlineStyle = 'background-color: #d4edda; border-left: 4px solid #28a745; color: transparent;';
                        break;
                    case 'diff-removed':
                        inlineStyle = 'background-color: #f8d7da; border-left: 4px solid #dc3545; color: transparent;';
                        break;
                    case 'diff-modified':
                        inlineStyle = 'background-color: #fff3cd; border-left: 4px solid #ffc107; color: transparent;';
                        break;
                }
                content += `<div class="diff-line ${lineClass}" style="${inlineStyle}">${this.escapeHtml(line) || '&nbsp;'}</div>`;
            } else {
                // 无高亮的行
                content += `<div class="diff-line" style="color: transparent;">${this.escapeHtml(line) || '&nbsp;'}</div>`;
            }
        }
        
        return content;
    }
    

    /**
     * 检查行是否与差异项匹配
     * @param {string} line - 行内容
     * @param {Object} diff - 差异对象
     * @param {number} editorNum - 编辑器编号（1或2）
     * @returns {boolean} 是否匹配
     */
    doesLineMatchDiff(line, diff, editorNum) {
        if (!diff.path) {
            return false;
        }
        
        // 标准化行内容（去除多余空格）
        const normalizedLine = line.trim();
        
        // 如果行是空的或只有括号/逗号，不匹配
        if (!normalizedLine || normalizedLine === '{' || normalizedLine === '}' || 
            normalizedLine === '[' || normalizedLine === ']' || normalizedLine === ',') {
            return false;
        }
        
        // 解析路径
        const pathParts = diff.path.split('.');
        const lastPathPart = pathParts[pathParts.length - 1];
        
        // 转义特殊字符
        const escapedPathPart = lastPathPart.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
        
        // 策略：精确匹配属性名 + 值
        // 检查行是否包含 "属性名": 的格式
        const propertyPattern = new RegExp(`"${escapedPathPart}"\\s*:`);
        if (!propertyPattern.test(normalizedLine)) {
            return false; // 属性名不匹配，直接返回
        }
        
        // 属性名匹配了，现在检查值是否也匹配
        // 根据差异类型和编辑器编号，决定应该匹配哪个值
        let valueToMatch;
        
        if (diff.type === 'added') {
            // 新增：只在编辑器2中，匹配新值
            valueToMatch = diff.newValue;
        } else if (diff.type === 'removed') {
            // 删除：只在编辑器1中，匹配旧值
            valueToMatch = diff.oldValue;
        } else if (diff.type === 'modified') {
            // 修改：编辑器1匹配旧值，编辑器2匹配新值
            valueToMatch = editorNum === 1 ? diff.oldValue : diff.newValue;
        }
        
        if (valueToMatch === undefined) {
            // 如果没有值信息，只匹配属性名
            return true;
        }
        
        // 检查行中是否包含这个值
        try {
            let valueStr;
            if (typeof valueToMatch === 'string') {
                valueStr = `"${valueToMatch}"`;
            } else if (typeof valueToMatch === 'object') {
                valueStr = JSON.stringify(valueToMatch);
            } else {
                valueStr = String(valueToMatch);
            }
            
            // 检查行中是否包含这个值
            if (normalizedLine.includes(valueStr)) {
                return true;
            }
            
            // 对于对象和数组，也检查紧凑格式（去除空格）
            if (typeof valueToMatch === 'object') {
                const compactLine = normalizedLine.replace(/\s+/g, '');
                const compactValue = valueStr.replace(/\s+/g, '');
                if (compactLine.includes(compactValue)) {
                    return true;
                }
            }
        } catch (e) {
            // 如果转换失败，只匹配属性名
            return true;
        }
        
        // 属性名匹配但值不匹配，返回 false
        return false;
    }
    
    /**
     * 严格匹配数组元素
     * @param {string} line - 行内容
     * @param {Object} diff - 差异对象
     * @returns {boolean} 是否匹配
     */
    matchArrayElementStrict(line, diff) {
        // 对于数组元素，只匹配包含完整值的行
        // 并且该行不应该是对象的属性定义
        
        // 如果行包含冒号，说明是对象属性，不是数组元素
        if (line.includes(':')) {
            return false;
        }
        
        // 检查是否包含值
        const value = diff.newValue !== undefined ? diff.newValue : diff.oldValue;
        if (value === undefined) {
            return false;
        }
        
        try {
            // 对于简单值，检查完整匹配
            if (typeof value === 'string') {
                // 字符串值应该带引号
                return line.includes(`"${value}"`);
            } else if (typeof value === 'number' || typeof value === 'boolean') {
                // 数字和布尔值直接匹配
                const valueStr = String(value);
                // 确保是完整的值，不是部分匹配
                const regex = new RegExp(`\\b${valueStr}\\b`);
                return regex.test(line);
            } else if (typeof value === 'object') {
                // 对象或数组，检查 JSON 字符串
                const valueStr = JSON.stringify(value);
                return line.includes(valueStr);
            }
        } catch (e) {
            return false;
        }
        
        return false;
    }
    
    /**
     * 检查行中是否包含特定值
     * @param {string} line - 行内容
     * @param {*} value - 值
     * @returns {boolean} 是否包含
     */
    doesLineContainValue(line, value) {
        // 检查行中是否包含特定值
        try {
            // 对于字符串值，检查是否包含该字符串
            if (typeof value === 'string') {
                return line.includes(`"${value}"`);
            }
            
            // 对于其他类型的值，转换为JSON字符串后检查
            const valueStr = JSON.stringify(value);
            return line.includes(valueStr);
        } catch (e) {
            // 如果转换出错，直接比较字符串表示
            return line.includes(String(value));
        }
    }
    
    /**
     * HTML转义
     * @param {string} text - 要转义的文本
     * @returns {string} 转义后的文本
     */
    escapeHtml(text) {
        return text
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#039;');
    }
}

// 导出类
if (typeof module !== 'undefined' && module.exports) {
    module.exports = HighlightManager;
}